function broadcast(componentName, eventName, params) {
    this.$children.forEach(element => {
        const name = element.$options.name;
        if (name === componentName) {
            element.$emit.apply(element, [eventName].concat(params))
        } else {
            broadcast.apply(element, [componentName, eventName].concat([params]))
        }
    });
}

export default {
  methods: {
    dispatch(componentName, eventName, params) {
      let _parent = this.$parent || this.$root;   // 父实例 || 根实例
      let name = _parent.$options.name;
      
      while (_parent && (!name || name !== componentName)) {
        /** 通过 _while_ 语句，不断向上遍历更新当前组件, 
         *  直到匹配到 componentName 和 上级组件name一致时，退出循环;
         *  否则 更新当前的组件name和parent, 继续循环。
        */          
        _parent = _parent.$parent;

        if (_parent) {
            name = _parent.$options.name;
        }
      }
      if (_parent) {
        _parent.$emit.apply(_parent, [eventName].concat(params));
      }
    },
    broadcast(componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params)
    }
  }
}